home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / interapplication comm / 7edit / source / svaecreate.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  12.3 KB  |  459 lines

  1. /*
  2.     File:        SVAECreate.c
  3.  
  4.     Contains:    
  5.  
  6.     Written by: Original version by Jon Lansdell and Nigel Humphreys.
  7.                 3.1 updates by Greg Sutton.
  8.  
  9.     Copyright:    Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
  10.  
  11.                 You may incorporate this Apple sample source code into your program(s) without
  12.                 restriction. This Apple sample source code has been provided "AS IS" and the
  13.                 responsibility for its operation is yours. You are not permitted to redistribute
  14.                 this Apple sample source code as "Apple sample source code" after having made
  15.                 changes. If you're going to re-distribute the source, we require that you make
  16.                 it clear in the source that the code was descended from Apple sample source
  17.                 code, but that you've made changes.
  18.  
  19.     Change History (most recent first):
  20.                 7/20/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  21.                 
  22.  
  23. */
  24. #include "SVAECreate.h"
  25.  
  26. #include "SVEditGlobals.h"
  27. #include "SVEditWindow.h"
  28. #include "SVEditAEUtils.h"
  29. #include "SVAETextUtils.h"
  30. #include "SVAppleEvents.h"
  31.  
  32. #include "SVAEAccessors.h"
  33. #include "SVAERecording.h"
  34. #include "SVAESelect.h"
  35. #include "SVAEWindowUtils.h"
  36. #include "SVAESetData.h"
  37.  
  38.  
  39. #pragma segment AppleEvent
  40.  
  41.  
  42. // ------------------------------------------------------------------------
  43. //    Name:         DoNewElement
  44. //    Purpose:    Handles the NewElement AppleEvent. Creates windows and
  45. //                text.
  46. // ------------------------------------------------------------------------
  47.  
  48. pascal OSErr    DoNewElement(const AppleEvent    *theAppleEvent,
  49.                                     AppleEvent    *reply, 
  50.                                     long        handlerRefCon)
  51. {
  52. #pragma unused (handlerRefCon)
  53.  
  54.     DescType    returnedType,
  55.                 newElemClass;
  56.     Size        actualSize;
  57.     AEDesc        dataDesc = {typeNull, NULL},
  58.                 insertHereDesc = {typeNull, NULL},
  59.                 propertyDesc = {typeNull, NULL},
  60.                 insertData = {typeNull, NULL},
  61.                 resultDesc = {typeNull, NULL};
  62.     OSErr       ignoreErr,
  63.                 err;
  64.         
  65.     err = AEGetParamPtr(theAppleEvent, keyAEObjectClass, typeType,
  66.                             &returnedType, (Ptr)&newElemClass, sizeof(newElemClass), &actualSize);
  67.     if (noErr != err) goto done;        // We have to know what object to create
  68.     
  69.         // Get optional parameters
  70.     ignoreErr = AEGetParamDesc(theAppleEvent, keyAEData, typeWildCard, &dataDesc);
  71.     ignoreErr = AEGetParamDesc(theAppleEvent, keyAEInsertHere, typeWildCard, &insertHereDesc);
  72.     ignoreErr = AEGetParamDesc(theAppleEvent, keyAEPropData, typeWildCard, &propertyDesc);
  73.             
  74.         // check for missing required parameters
  75.     err = GotRequiredParams(theAppleEvent);
  76.     if (noErr != err) goto done;
  77.  
  78.     switch (newElemClass)
  79.     {
  80.         case cWindow:
  81.         case cDocument:
  82.             err = CreateWindow(&dataDesc, &insertHereDesc, &propertyDesc, &resultDesc);
  83.             break;
  84.             
  85.         case cChar:
  86.         case cText:
  87.         case cWord:
  88.         case cParagraph:
  89.             err = CreateText(newElemClass, &dataDesc, &insertHereDesc, &propertyDesc, &resultDesc);
  90.             break;
  91.             
  92.         default:
  93.             err = errAEWrongDataType;
  94.     }
  95.     
  96.     err = AddResultToReply(&resultDesc, reply, err);
  97.  
  98. done:            
  99.     if (dataDesc.dataHandle) 
  100.         AEDisposeDesc(&dataDesc);
  101.     if (insertHereDesc.dataHandle) 
  102.         AEDisposeDesc(&insertHereDesc);
  103.     if (propertyDesc.dataHandle) 
  104.         AEDisposeDesc(&propertyDesc);
  105.     if (resultDesc.dataHandle) 
  106.         AEDisposeDesc(&resultDesc);
  107.         
  108.     return(err);
  109. } // DoNewElement
  110.  
  111.  
  112. OSErr    CreateWindow(AEDesc* dataDesc, AEDesc* insertHereDesc,
  113.                                                 AEDesc* propertyDesc, AEDesc* result)
  114. {
  115.     AEDesc        insertDesc = {typeNull, NULL};
  116.     DescType     insertType;
  117.     DPtr        docPtr;
  118.     WindowPtr    behindWindow;
  119.     OSErr        err;
  120.  
  121.      err = GetInsertDescFromInsertHere(insertHereDesc, &insertDesc, &insertType);
  122.     if (noErr != err) goto done;
  123.     
  124.     err = GetBehindWindow(&insertDesc, insertType, &behindWindow);
  125.     if (noErr != err) goto done;
  126.     
  127.     docPtr = NewDocument(false, behindWindow);
  128.  
  129.     if (! docPtr)
  130.     {
  131.         err = errAENoSuchObject;
  132.         goto done;
  133.     }
  134.  
  135.     if (propertyDesc->dataHandle)
  136.         err = SetWindowPropertyRecord(docPtr->theWindow, propertyDesc);
  137.     if (noErr != err) goto done;
  138.  
  139.     if (dataDesc->dataHandle)
  140.     {
  141.         err = SetWindowData(docPtr->theWindow, dataDesc);
  142.         docPtr->dirty = true;
  143.     }
  144.     else
  145.         docPtr->dirty = false;
  146.     if (noErr != err) goto done;
  147.  
  148.     ShowWindow(docPtr->theWindow);
  149.     err = MakeWindowObj(docPtr->theWindow, result);
  150.  
  151. done:
  152.     if (insertDesc.dataHandle)
  153.         AEDisposeDesc(&insertDesc);
  154.  
  155.     return(err);
  156. }
  157.  
  158. OSErr    GetBehindWindow(AEDesc* insertDesc, DescType insertType, WindowPtr* behindWindow)
  159. {
  160.     AEDesc            windowDesc = {typeNull, NULL};
  161.     WindowToken        aWindowToken;
  162.     Size            actualSize;
  163.     short            index;
  164.     OSErr            err;
  165.  
  166.     if (typeNull == insertDesc->descriptorType)
  167.     {
  168.         *behindWindow = (WindowPtr) -1L;
  169.         return(noErr);
  170.     }
  171.     
  172.     err = AECoerceDesc(insertDesc, typeMyWndw, &windowDesc);
  173.     if (noErr != err) goto done;
  174.  
  175.     GetRawDataFromDescriptor(&windowDesc, (Ptr)&aWindowToken,
  176.                                     sizeof(aWindowToken), &actualSize);
  177.  
  178.     switch (insertType)
  179.     {
  180.         case kAEBeginning:
  181.             *behindWindow = (WindowPtr) -1L;
  182.             break;
  183.     
  184.         case kAEEnd:
  185.             *behindWindow = NULL;
  186.             break;
  187.         
  188.         case kAEBefore:
  189.             index = GetNthWindowOfWindowPtr(aWindowToken.tokenWindow);
  190.             if (index > 1)
  191.                 *behindWindow = GetWindowPtrOfNthWindow(index - 1);
  192.             else
  193.                 *behindWindow = (WindowPtr) -1L;    // Stick at front because no
  194.             break;                                    // windows before that.
  195.         
  196.         case kAEAfter:
  197.             *behindWindow = aWindowToken.tokenWindow;
  198.             break;
  199.         
  200.         case kAEReplace:
  201.         default:
  202.             err = errAEEventFailed;        // We won't allow a new window to replace an existing one
  203.     }
  204.     
  205. done:
  206.     if (windowDesc.dataHandle)
  207.         (void)AEDisposeDesc(&windowDesc);
  208.  
  209.     return(err);
  210. }
  211.  
  212. OSErr    SetWindowPropertyRecord(WindowPtr theWindow, AEDesc* propertyRecord)
  213. {
  214.     WindowPropToken        aWindowPropToken;
  215.     AEDesc                dataDesc = {typeNull, NULL},
  216.                         propertyDesc = {typeNull, NULL};
  217.     AEKeyword            theAEKeyword;
  218.     long                index;
  219.     OSErr                err;
  220.     
  221.     aWindowPropToken.tokenWindowToken.tokenWindow = theWindow;
  222.                                     
  223.     err = AECountItems(propertyRecord, &index);
  224.     if (noErr != err) goto done;
  225.     
  226.             // Step through each property - creating a window property token AEDesc
  227.             // and letting SetWindowProperty() do the work.
  228.     for (; index > 0; index--)
  229.     {
  230.         err = AEGetNthDesc(propertyRecord, index, typeWildCard, &theAEKeyword, &dataDesc);
  231.         if (noErr != err) goto done;
  232.  
  233.         aWindowPropToken.tokenProperty = theAEKeyword;
  234.         err = AECreateDesc(typeMyWindowProp, (Ptr)&aWindowPropToken, 
  235.                                         sizeof(aWindowPropToken), &propertyDesc);
  236.         if (noErr != err) goto done;
  237.         
  238.         err = DoSetWindowProperty(&propertyDesc, &dataDesc);
  239.         if (noErr != err) goto done;
  240.         
  241.         if (dataDesc.dataHandle)
  242.             AEDisposeDesc(&dataDesc);
  243.         if (propertyDesc.dataHandle)
  244.             AEDisposeDesc(&propertyDesc);
  245.     }
  246.     
  247. done:
  248.     if (dataDesc.dataHandle)
  249.         AEDisposeDesc(&dataDesc);
  250.     if (propertyDesc.dataHandle)
  251.         AEDisposeDesc(&propertyDesc);
  252.     
  253.     return(err);
  254. }
  255.  
  256. // We'll just assume it's text and put it through as the selection.
  257.  
  258. OSErr    SetWindowData(WindowPtr theWindow, AEDesc* dataDesc)
  259. {
  260.     WindowPropToken        aWindowPropToken;
  261.     AEDesc                propertyDesc = {typeNull, NULL};
  262.     OSErr                err;
  263.     
  264.     aWindowPropToken.tokenWindowToken.tokenWindow = theWindow;
  265.     aWindowPropToken.tokenProperty = pSelection;
  266.                                     
  267.     err = AECreateDesc(typeMyWindowProp, (Ptr)&aWindowPropToken, 
  268.                                     sizeof(aWindowPropToken), &propertyDesc);
  269.     if (noErr != err) goto done;
  270.         
  271.     err = DoSetWindowProperty(&propertyDesc, dataDesc);
  272.  
  273. done:
  274.     if (propertyDesc.dataHandle)
  275.         AEDisposeDesc(&propertyDesc);
  276.  
  277.     return(err);
  278. }
  279.  
  280.  
  281. OSErr    CreateText(DescType textType, AEDesc* dataDesc, AEDesc* insertHereDesc,
  282.                                                 AEDesc* propertyDesc, AEDesc* result)
  283. {
  284.     AEDesc        insertDesc = {typeNull, NULL};
  285.     DescType     insertType;
  286.     TextToken    anInsertToken;
  287.     short        ignore;
  288.     OSErr        err = noErr;
  289.  
  290.      err = GetInsertDescFromInsertHere(insertHereDesc, &insertDesc, &insertType);
  291.     if (noErr != err) goto done;
  292.     
  293.     if (typeNull == insertType)        // Default to setting the selection in the front window
  294.         err = GetWindowSelection(FrontWindow(), &anInsertToken, &ignore);
  295.     else                            // Otherwise get a selection from the insertDesc
  296.         err = GetInsertToken(&insertDesc, insertType, &anInsertToken);
  297.         
  298.     if (noErr != err) goto done;
  299.     
  300.     err = CreateAtTextToken(textType, dataDesc, &anInsertToken, propertyDesc, result);
  301.  
  302. done:
  303.     if (insertDesc.dataHandle)
  304.         AEDisposeDesc(&insertDesc);
  305.  
  306.     return(err);
  307. }
  308.  
  309. // Get a TextToken for the location of where to insert the text. If the insertType is
  310. // a relative position then work this out. Otherwise just use the insertDesc.
  311.  
  312. OSErr    GetInsertToken(AEDesc* insertDesc, DescType insertType, TextToken* resultToken)
  313. {
  314.     AEDesc        textDesc = {typeNull, NULL};
  315.     TextToken    aTextToken;
  316.     Size        actualSize;
  317.     OSErr        err;
  318.  
  319.     err = AECoerceDesc(insertDesc, typeMyText, &textDesc);
  320.     if (noErr != err) goto done;
  321.  
  322.     GetRawDataFromDescriptor(&textDesc, (Ptr)&aTextToken,
  323.                                     sizeof(aTextToken), &actualSize);
  324.     resultToken->tokenWindow = aTextToken.tokenWindow;
  325.  
  326.     switch (insertType)
  327.     {
  328.         case kAEBeginning:
  329.         case kAEBefore:
  330.             resultToken->tokenOffset = aTextToken.tokenOffset;
  331.             resultToken->tokenLength = 0;
  332.             break;
  333.     
  334.         case kAEEnd:
  335.         case kAEAfter:
  336.             resultToken->tokenOffset = aTextToken.tokenOffset + aTextToken.tokenLength;
  337.             resultToken->tokenLength = 0;
  338.             break;
  339.         
  340.         case kAEReplace:
  341.         default:            // default is probably some text token to replace
  342.                             // e.g make new word at middle word of document 1 with data "Iris"
  343.                             // It has been coerced to text so it's okay
  344.             resultToken->tokenOffset = aTextToken.tokenOffset;
  345.             resultToken->tokenLength = aTextToken.tokenLength;
  346.             break;
  347.     }
  348.  
  349. done:
  350.     if (textDesc.dataHandle)
  351.         (void)AEDisposeDesc(&textDesc);
  352.     
  353.     return(err);
  354. }
  355.  
  356. // Create text using the dataDesc (which could be text, styled text, etc…) at the
  357. // the location held in the TextToken.
  358. // Properties in the propertyDesc will be applied to the new text.
  359. // Returns an object specifier to the text.
  360.  
  361. OSErr       CreateAtTextToken(DescType textType, const AEDesc* dataDesc, TextToken* theToken,
  362.                                                     AEDesc* propertyDesc, AEDesc* result)
  363. {
  364. #pragma unused(textType)
  365.  
  366.     DPtr        docPtr;
  367.     TextToken    aSelectionToken;
  368.     short        oldLength;
  369.     OSErr        err;
  370.  
  371.     docPtr = DPtrFromWindowPtr(theToken->tokenWindow);
  372.     
  373.     if (! docPtr)
  374.         return(errAENoSuchObject);
  375.  
  376.             // Copy the current selection - so we can restore it after
  377.     err = GetWindowSelection(theToken->tokenWindow, &aSelectionToken, &oldLength);
  378.     if (noErr != err) goto done;
  379.  
  380.             // Set the selection we want to insert the new text into
  381.     err = SelectTextToken(theToken);
  382.     if (noErr != err) goto done;
  383.  
  384.     err = PutStyledTextFromDescIntoTEHandle(dataDesc, docPtr->theText);
  385.     if (noErr != err) goto done;
  386.     
  387.             // Update the selection and get the length of the insertion
  388.     err = UpdateSelectionToken(theToken, &aSelectionToken, oldLength,
  389.                                                         &theToken->tokenLength);
  390.     if (noErr != err) goto done;
  391.     
  392.     // Need to check on token type in here and make what user wanted
  393.     // e.g. make sure a word is a word.
  394.     // Would have to remember to balance token for any chages to TEHandle.
  395.  
  396.     if (propertyDesc->dataHandle)
  397.     {                                    // I doubt we'll handle setting the text property
  398.                                         // or anything that changes the token length… oh well
  399.         err = SetTextPropertyRecord(theToken, propertyDesc);
  400.         if (noErr != err) goto done;
  401.     }
  402.             // Make the returned object
  403.     err = MakeTextObjFromToken(theToken, result);
  404.     
  405. done:
  406.     return(err);
  407. }
  408.  
  409.  
  410. // Take a TextToken and apply the properties in the propertyRecord descriptor
  411. // to the text.
  412. // e.g. make new word at beginning of document 1 with data "Bert" ¬
  413. //                                with properties {size:32, font:"Courier"}
  414. // The with properties part is the property record.
  415.  
  416. OSErr    SetTextPropertyRecord(TextToken* aTextToken, AEDesc* propertyRecord)
  417. {
  418.     TextPropToken        aTextPropToken;
  419.     AEDesc                dataDesc = {typeNull, NULL},
  420.                         propertyDesc = {typeNull, NULL};
  421.     AEKeyword            theAEKeyword;
  422.     long                index;
  423.     OSErr                err;
  424.     
  425.     aTextPropToken.tokenTextToken = *aTextToken;
  426.                                     
  427.     err = AECountItems(propertyRecord, &index);
  428.     if (noErr != err) goto done;
  429.     
  430.             // Step through each property - creating a window property token AEDesc
  431.             // and letting SetWindowProperty() do the work.
  432.     for (; index > 0; index--)
  433.     {
  434.         err = AEGetNthDesc(propertyRecord, index, typeWildCard, &theAEKeyword, &dataDesc);
  435.         if (noErr != err) goto done;
  436.  
  437.         aTextPropToken.tokenProperty = theAEKeyword;
  438.         err = AECreateDesc(typeMyTextProp, (Ptr)&aTextPropToken, 
  439.                                         sizeof(aTextPropToken), &propertyDesc);
  440.         if (noErr != err) goto done;
  441.         
  442.         err = SetTextProperty(&propertyDesc, &dataDesc);
  443.         if (noErr != err) goto done;
  444.         
  445.         if (dataDesc.dataHandle)
  446.             AEDisposeDesc(&dataDesc);
  447.         if (propertyDesc.dataHandle)
  448.             AEDisposeDesc(&propertyDesc);
  449.     }
  450.     
  451. done:
  452.     if (dataDesc.dataHandle)
  453.         AEDisposeDesc(&dataDesc);
  454.     if (propertyDesc.dataHandle)
  455.         AEDisposeDesc(&propertyDesc);
  456.     
  457.     return(err);
  458. }
  459.